#include <cstring>
#include <cmath>
#include <iostream>  //预处理器指令 a PREPROCESSOR directive
using namespace std; // 使定义可见   make definitions visible
#include <vector>
#include <array>
#include <new>

/*
  13.1 继承的基础介绍
  公有继承
  成员初始化列表作用于构造方法

*/


// simple base class
// 乒乓球运动员
class TableTennisPlayer
{
  private:
    string firstname; // 姓
    string lastname;  // 名
    bool hasTable;    // 是否有桌球
  public:
    TableTennisPlayer(const string &fn = "none",
                      const string &ln = "none", bool ht = false);
    void Name() const;
    bool HasTable() const { return hasTable; };
    void ResetTable(bool v) { hasTable = v; };
};

// simple derived class 
// 简单派生类 - 评分玩家 - 公有继承
class RatedPlayer : public TableTennisPlayer
{
  private:
    unsigned int rating; //成员在比赛中的比分

  public:
    RatedPlayer(unsigned int r = 0, const string &fn = "none",
                const string &ln = "none", bool ht = false);

    RatedPlayer(unsigned int r, const TableTennisPlayer &tp);

    unsigned int Rating() const { return rating; }
    void ResetRating(unsigned int r) { rating = r; }
};

int main()
{

  TableTennisPlayer player1("Chuck", "Blizzard", true);
  TableTennisPlayer player2("Tara", "Boomdea", false);

  player1.Name();

  RatedPlayer rplayer1(1140, "Mallory", "Duck", true);
  rplayer1.Name();          // derived object uses base method

  //基类指针可以在不进行显式类型转换的情况下指向派生类对象；基类引用可以在不进行显式类型转换的情况下引用派生类对象
  TableTennisPlayer& rt = rplayer1;  
  TableTennisPlayer* pt = &rplayer1;
  rt.Name();//invokeName()with reference
  pt->Name();//invokeName()with pointer


}

// 父类的方法 - 成员初始化列表
TableTennisPlayer::TableTennisPlayer(const string &fn, const string &ln, bool ht) : firstname(fn), lastname(ln), hasTable(ht) {}

// 也可以这样做
/*
  TableTennisPlayer::TableTennisPlayer (const string & fn,const string & ln, bool ht) {
    firstname = fn;
    lastname = ln;
    hasTable = ht;
  }
*/

void TableTennisPlayer::Name() const
{
  std::cout << lastname << ", " << firstname << endl;
}

// RatedPlayer methods
// 派生类的方法
RatedPlayer::RatedPlayer(unsigned int r, const string &fn, const string &ln, bool ht) : TableTennisPlayer(fn, ln, ht)
{
  rating = r;
}

RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer &tp)
    : TableTennisPlayer(tp), rating(r)
{
}

void Show(const TableTennisPlayer &rt)
{
  cout << "Name:";
  rt.Name();
  cout << "\nTable:";
  if (rt.HasTable())
    cout << "yes\n";
  else
    cout << "no\n";
}
